package blockingQueue;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: tao
 * Date: 2023-12-03
 * Time: 14:45
 */
class MyBlockingQueue {
    Object locker = new Object();
    private String elems[] = null;
    private int head = 0;//记录头结点
    private  int tail = 0;//记录尾结点
    private int size = 0;//队列元素个数
    //构造方法，定义队列的容量大小
    public MyBlockingQueue(int capacity) {
        this.elems = new String[capacity];
    }
    //入队列
    public void put(String elem) throws InterruptedException {
        synchronized (locker) {
            //判断容量满了没，满了就不能入队列，要阻塞等待
            while (size >= this.elems.length) {
                //阻塞等待，先不写，先实现普通功能的队列
                synchronized (locker) {
                    locker.wait();
                }
            }
            //因为这些都是写操作，也有读操作，多线程并发执行时，写操作是线程不安全的，要把这些打包成一个原子，加锁
            synchronized (locker) {
                //入队列
                elems[tail] = elem;
                tail++;
                //因为是循环队列，所以要判断尾巴有没有超过容量大小下标，超过了就要从0开始了
                if(tail > elems.length) {
                    tail = 0;
                }
                //队列元素要++
                size++;
                locker.notify();
            }
        }
    }

    //出队列
    public String take() throws InterruptedException {
        String elem = null;
        //因为这些都是写操作，也有读操作，多线程并发执行时，写操作是线程不安全的，要把这些打包成一个原子，加锁
        synchronized (locker) {
            //要判断队列是不是空的，空就不能出队列了，要阻塞等待
            while (size == 0) {
                //阻塞等待，因为是先实现普通队列的功能，所以后面再补充
                synchronized (locker) {
                    locker.wait();
                }
            }
            elem = elems[head];
            head++;
            //因为是循环队列，所以要判断头结点有没有超过容量大小下标，超过了就要0开始了
            if(head >= elems.length) {
                head = 0;
            }
            //出队列后，队列元素要--
            size--;
            locker.notify();
            return elem;
        }
    }
}
public class MyBlockingQueueTest {
    public static void main(String[] args) throws InterruptedException {
        MyBlockingQueue queue = new MyBlockingQueue(10);
        queue.put("aaa");
        String elem = queue.take();
        System.out.println(elem);
    }
}
